package com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.resp.UserInfoResp;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTips;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsUserStudentRelation;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsUserStudentRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsSchoolFeesDelay;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsSchoolFeesDelayDetail;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsSchoolFeesDelayProcess;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.*;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.*;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsSchoolFeesDelayDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsSchoolFeesDelayMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsSchoolFeesDelayMpjMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsSchoolFeesDelayProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.SmsWnsSchoolFeesDelayService;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util.AssistantUtil;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util.SecondaryCollegeLeaderUtil;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util.StudentUtil;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.SmsWorkGroupApplication;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.isExportProcessConstant.EXPORT_PROCESS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.paymentExamineStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.student.constant.StudentInfoCommonConstant.PER_SHEET_NUM;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayObjectTypeConstant.SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayObjectTypeConstant.SCHOOL_FEES_DELAY_OBJECT_TYPE_ROLE;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayProcessNameConstant.PROCESS_NAME_ASSISTANT;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayProcessNameConstant.PROCESS_NAME_SECONDARY_COLLEGE;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.SchoolFeesDelayTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_ALLOW_STATUS;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_TIME;

/**
 * <p>
 * 学费缓交表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-01-30
 */
@Service
public class SmsWnsSchoolFeesDelayServiceImpl extends ServiceImpl<SmsWnsSchoolFeesDelayMapper, SmsWnsSchoolFeesDelay> implements SmsWnsSchoolFeesDelayService {
    @Resource
    private FileSavePathConstant fileSavePathConstant;
    @Resource
    private SmsWnsSchoolFeesDelayMapper smsWnsSchoolFeesDelayMapper;
    @Resource
    private SmsWnsSchoolFeesDelayProcessMapper smsWnsSchoolFeesDelayProcessMapper;
    @Resource
    private SmsWnsSchoolFeesDelayDetailMapper smsWnsSchoolFeesDelayDetailMapper;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private NewTipsUtil newTipsUtil;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private ApiModelUtil apiModelUtil;
    @Resource
    private SmsRoleMapper smsRoleMapper;
    @Resource
    private SmsNewTipsMapper smsNewTipsMapper;
    @Resource
    private SmsNewTipsRecordMapper smsNewTipsRecordMapper;
    @Resource
    private AssistantUtil assistantUtil;
    @Resource
    private SecondaryCollegeLeaderUtil secondaryCollegeLeaderUtil;
    @Resource
    private StudentUtil studentUtil;
    @Resource
    private SmsUserStudentRelationMapper smsUserStudentRelationMapper;
    @Resource
    private SmsStudentInfoMapper smsStudentInfoMapper;
    @Resource
    private SmsWnsSchoolFeesDelayMpjMapper smsWnsSchoolFeesDelayMpjMapper;

    @Override
    public ResponseResult getAssistantAndOrgLeader(String userId) {
        //学生的院系 专业 年级 班级信息
        SmsSchoolFeesDelayStudentInfoResp schoolFeesDelayStudentInfoResp = new SmsSchoolFeesDelayStudentInfoResp();
        StudentOrgInfoResp studentOrgInfo = studentUtil.getStudentCollegeMajorClassInfo(userId);
        if (studentOrgInfo == null) {
            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
        }
        //检验是否设置了辅导员
        List<SmsUser> classTeacherUserInfoList = assistantUtil.getAssistantUserInfo(String.valueOf(studentOrgInfo.getClassId()));
        if (classTeacherUserInfoList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_ASSISTANT);
        }
        //检验是否设置了院负责人
        String collegeLeaderId = secondaryCollegeLeaderUtil.getSecondaryCollegeLeader(studentOrgInfo.getCollegeId());
        if (isNullOrEmpty(collegeLeaderId)) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_LEADER);
        }
        //查学生信息
        SmsUserStudentRelation studentRelation = smsUserStudentRelationMapper.selectOne(new LambdaQueryWrapper<SmsUserStudentRelation>()
                .eq(SmsUserStudentRelation::getUserId, userId));
        if (studentRelation == null) {
            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
        }

        SmsStudentInfo studentInfo = smsStudentInfoMapper.selectById(studentRelation.getStuId());
        if (studentInfo == null) {
            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
        }
        BeanUtils.copyProperties(studentOrgInfo,schoolFeesDelayStudentInfoResp);
        schoolFeesDelayStudentInfoResp.setStuAddr(studentInfo.getStuAddr());
        schoolFeesDelayStudentInfoResp.setStuName(studentInfo.getStuName());
        schoolFeesDelayStudentInfoResp.setStuIdCard(studentInfo.getStuIdCard());
        schoolFeesDelayStudentInfoResp.setStuSex(studentInfo.getStuSex());
        return CommonResult.success(schoolFeesDelayStudentInfoResp);
    }

    @Override
    @Transactional
    public ResponseResult addSchoolFeesDelay(SmsWnsSchoolFeesDelayReq schoolFeesDelayReq, String userId) {

        if (isNullOrEmpty(schoolFeesDelayReq.getCollegeId(),schoolFeesDelayReq.getStuName(),schoolFeesDelayReq.getStuSex(),schoolFeesDelayReq.getCollegeName(),
                schoolFeesDelayReq.getMajorId(),schoolFeesDelayReq.getMajorName(),schoolFeesDelayReq.getStuAddress(),schoolFeesDelayReq.getDelayReason(),
                schoolFeesDelayReq.getShouldMoney(),schoolFeesDelayReq.getAfterMoney(),schoolFeesDelayReq.getBeforeMoney(),schoolFeesDelayReq.getDeliveryDate(),
                schoolFeesDelayReq.getParentName(),schoolFeesDelayReq.getParentTel(),schoolFeesDelayReq.getStuIdCard())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsWnsSchoolFeesDelayProcess> fillProcessList =
                smsWnsSchoolFeesDelayProcessMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayProcess>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsWnsSchoolFeesDelayProcess::getProcessIsUse, true)
                        .orderByAsc(SmsWnsSchoolFeesDelayProcess::getProcessSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (schoolFeesDelayReq.getProcessList() == null || schoolFeesDelayReq.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsWnsSchoolFeesDelayProcess> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<String> result = schoolFeesDelayReq.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                                        .map(SmsWnsSchoolFeesDelayDetailReq::getId)
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                if (result.size() > 0) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_PROCESS_NOT_FILL);
            }
        }

        //创建申请表
        SmsWnsSchoolFeesDelay addSchoolFeesDelay = new SmsWnsSchoolFeesDelay();
        BeanUtils.copyProperties(schoolFeesDelayReq, addSchoolFeesDelay);
        addSchoolFeesDelay.setUserId(userId);
        addSchoolFeesDelay.setAllowStatus(SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW);
        smsWnsSchoolFeesDelayMapper.insert(addSchoolFeesDelay);

        //申请表id
        String applyId = addSchoolFeesDelay.getId();
        if (isNullOrEmpty(applyId)) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        //获取该学生的辅导员和二级院领导
        StudentOrgInfoResp studentOrgInfo = studentUtil.getStudentCollegeMajorClassInfo(userId);
        if (isNullOrEmpty(studentOrgInfo)) {
            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
        }
        //辅导员
        List<SmsUser> classTeacherUserInfoList = assistantUtil.getAssistantUserInfo(String.valueOf(studentOrgInfo.getClassId()));
        if (classTeacherUserInfoList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_ASSISTANT);
        }
        //辅导员用户信息
        SmsUser assistantInfo = classTeacherUserInfoList.get(0);
        //二级学院负责人
        String collegeLeaderId = secondaryCollegeLeaderUtil.getSecondaryCollegeLeader(studentOrgInfo.getCollegeId());
        if (isNullOrEmpty(collegeLeaderId)) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_LEADER);
        }

        //创建审批流程
        List<SmsWnsSchoolFeesDelayProcess> originProcessList = smsWnsSchoolFeesDelayProcessMapper.selectList(
                new QueryWrapper<SmsWnsSchoolFeesDelayProcess>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayProcess::getProcessIsUse, true)
                        .orderByAsc(SmsWnsSchoolFeesDelayProcess::getProcessSort));
        if (originProcessList == null || originProcessList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsWnsSchoolFeesDelayProcess process : originProcessList) {
            //判断管理员是否配置初始流程(辅导员和二级学院除外)
            List<String> filterProcess = new ArrayList<>();
            filterProcess.add(PROCESS_NAME_ASSISTANT);
            filterProcess.add(PROCESS_NAME_SECONDARY_COLLEGE);
            if (!filterProcess.contains(process.getProcessName())) {
                if (!process.getProcessIsApplicationEdit()) {
                    if (isNullOrEmpty(process.getProcessObjectId()) || isNullOrEmpty(process.getProcessObjectType())) {
                        ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.AGREEMENT_PROCESS_NOT_SETTING));
                    }
                }
            }


            SmsWnsSchoolFeesDelayDetail addDetail = new SmsWnsSchoolFeesDelayDetail();
            addDetail.setApplyId(applyId);
            addDetail.setProcessId(process.getId());
            addDetail.setProcessIsSign(process.getProcessIsSign());
            addDetail.setProcessIsStamp(process.getProcessIsStamp());
            addDetail.setProcessName(process.getProcessName());
            addDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW);
            addDetail.setDetailSort(sort++);

            //申请人可编辑流程
            if (process.getProcessIsApplicationEdit()) {
                List<SmsWnsSchoolFeesDelayDetailReq> filterList = schoolFeesDelayReq.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_PROCESS_NOT_FILL));
                }
                SmsWnsSchoolFeesDelayDetailReq fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessObjectId(fillProcessReq.getProcessObjectId());
                addDetail.setProcessObjectType(SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON);
            } else {
                //辅导员
                if (process.getProcessName().equals(PROCESS_NAME_ASSISTANT)) {
                    addDetail.setProcessObjectId(assistantInfo.getId());
                    addDetail.setProcessObjectType(SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON);
                //二级学院领导
                }else if(process.getProcessName().equals(PROCESS_NAME_SECONDARY_COLLEGE)){
                    addDetail.setProcessObjectId(collegeLeaderId);
                    addDetail.setProcessObjectType(SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON);
                }else {
                    addDetail.setProcessObjectId(process.getProcessObjectId());
                    addDetail.setProcessObjectType(process.getProcessObjectType());
                }
            }
            smsWnsSchoolFeesDelayDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsWnsSchoolFeesDelayDetail firstDetail =
                smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, applyId)
                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, 1)
                        .orderByAsc(SmsWnsSchoolFeesDelayDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
        }
        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                userId,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_AGREEMENT_APPLICATION,
                applyId,
                firstDetail.getId());
        return CommonResult.success();

    }

    @Override
    @Transactional
    public ResponseResult cancelSchoolFeesDelay(SmsWnsSchoolFeesDelayCancelReq cancelReq, String userId) {
        if (isNullOrEmpty(cancelReq.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //查看审批表是否存在且是否为本人
        SmsWnsSchoolFeesDelay schoolFeesDelay =
                smsWnsSchoolFeesDelayMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelay>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelay::getId, cancelReq.getApplyId())
                        .eq(SmsWnsSchoolFeesDelay::getUserId, userId));
        if (schoolFeesDelay == null || isNullOrEmpty(schoolFeesDelay.getId())) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }
        if (schoolFeesDelay.getAllowStatus() != SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_CANCEL_FAIL_ALLOWED);
        }

        //撤回审批
        SmsWnsSchoolFeesDelay cancelSchoolFeesDelay = new SmsWnsSchoolFeesDelay();
        cancelSchoolFeesDelay.setId(cancelReq.getApplyId());
        cancelSchoolFeesDelay.setAllowStatus(SCHOOL_FEES_DELAY_STATUS_CANCEL);
        cancelSchoolFeesDelay.setEndTime(new Date());
        smsWnsSchoolFeesDelayMapper.updateById(cancelSchoolFeesDelay);

        //修改节点状态
        SmsWnsSchoolFeesDelayDetail cancelSchoolFeesDelayDetail = new SmsWnsSchoolFeesDelayDetail();
        cancelSchoolFeesDelayDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_CANCEL);

        smsWnsSchoolFeesDelayDetailMapper.update(cancelSchoolFeesDelayDetail, new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                .lambda()
                .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, cancelReq.getApplyId())
                .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus,SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(cancelReq.getApplyId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult allowSchoolFeesDelay(SmsWnsSchoolFeesDelayAllowReq allowReq, String userId) {
        if (isNullOrEmpty(allowReq.getApplyId()) || isNullOrEmpty(allowReq.getDetailId()) || isNullOrEmpty(allowReq.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowReq.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_PASS && allowReq.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsSchoolFeesDelayDetail schoolFeesDelayDetail =
                smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                        .eq(SmsWnsSchoolFeesDelayDetail::getId, allowReq.getDetailId())
                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));
        if (schoolFeesDelayDetail == null || isNullOrEmpty(schoolFeesDelayDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止跳节点审批）
        if (schoolFeesDelayDetail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON) {
            if (!schoolFeesDelayDetail.getProcessObjectId().equals(userId)) {
                return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
            }

        } else {
            List<String> roleList = cacheUtil.getRoleList(userId);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(schoolFeesDelayDetail.getProcessObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
            }
        }

        if (!schoolFeesDelayDetail.getDetailSort().equals(1)) {
            SmsWnsSchoolFeesDelayDetail preDetail =
                    smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                            .lambda()
                            .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, schoolFeesDelayDetail.getDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
                }
            }
        }


        SmsWnsSchoolFeesDelayDetail allowDetail = new SmsWnsSchoolFeesDelayDetail();
        allowDetail.setId(allowReq.getDetailId());
        allowDetail.setDetailAllowStatus(allowReq.getDetailAllowStatus());
        if (!isNullOrEmpty(allowReq.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowReq.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(userId);

        if (schoolFeesDelayDetail.getProcessIsSign()) {
            allowDetail.setDetailAllowSign(allowReq.getDetailAllowSign());
        }
        if (schoolFeesDelayDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(allowReq.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowStamp(allowReq.getDetailAllowStamp());
        }
        smsWnsSchoolFeesDelayDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsWnsSchoolFeesDelayDetailMapper.selectCount(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                .lambda()
                .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId()));
        if (detailCount.equals(schoolFeesDelayDetail.getDetailSort()) || allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_DENY) {
            is_done = true;

            SmsWnsSchoolFeesDelay updateSchoolFeesDelay = new SmsWnsSchoolFeesDelay();
            updateSchoolFeesDelay.setId(allowReq.getApplyId());
            updateSchoolFeesDelay.setEndTime(nowDate);
            updateSchoolFeesDelay.setAllowStatus(allowReq.getDetailAllowStatus());
            smsWnsSchoolFeesDelayMapper.updateById(updateSchoolFeesDelay);
        }

        //节点驳回 重置其余节点状态
        if (allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_DENY) {
            SmsWnsSchoolFeesDelayDetail updateDetail = new SmsWnsSchoolFeesDelayDetail();
            updateDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_DENY_FINISH);
            smsWnsSchoolFeesDelayDetailMapper.update(updateDetail, new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                    .lambda()
                    .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                    .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));
        }

        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowReq.getApplyId(), userId, result_status);
        } else {
            SmsWnsSchoolFeesDelayDetail nextDetail =
                    smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                            .lambda()
                            .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, schoolFeesDelayDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowReq.getApplyId(),
                    userId,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getSchoolFeesDelayList(String searchStr, Integer applyType,Integer sort, String userId, Integer pageSize, Integer pageNum) {
        if (isNullOrEmpty(applyType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsWnsSchoolFeesDelayResp> respList = new ArrayList<>();
        int total = 0;
        if (applyType == SCHOOL_FEES_DELAY_TYPE_APPLY) {
            Page<SmsWnsSchoolFeesDelay> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsWnsSchoolFeesDelay> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsWnsSchoolFeesDelay::getUserId, userId);

            //排序方式 0:审批时间 1:审批状态
            if (!isNullOrEmpty(sort)) {
                if (sort == SORT_TYPE_TIME) {
                    queryWrapper.lambda().orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
                } else if (sort == SORT_TYPE_ALLOW_STATUS) {
                    queryWrapper.lambda()
                            .orderByAsc(SmsWnsSchoolFeesDelay::getAllowStatus)
                            .orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
                }
            }else {
                queryWrapper.lambda(). orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
            }
            if (!isNullOrEmpty(searchStr)) {
                queryWrapper.lambda().and(q -> {
                    q.like(SmsWnsSchoolFeesDelay::getStuName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getStuSex, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getMajorName, searchStr);
                });
            }
            smsWnsSchoolFeesDelayMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsWnsSchoolFeesDelay -> {
                        SmsWnsSchoolFeesDelayResp smsWnsSchoolFeesDelayResp = new SmsWnsSchoolFeesDelayResp();
                        BeanUtils.copyProperties(smsWnsSchoolFeesDelay, smsWnsSchoolFeesDelayResp);
                        smsWnsSchoolFeesDelayResp.setApplyId(smsWnsSchoolFeesDelay.getId());

                        SmsUser smsUser = cacheUtil.getUserInfo(smsWnsSchoolFeesDelay.getUserId());
                        UserInfoResp applyUserInfo = new UserInfoResp();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, applyUserInfo);
                        }
                        smsWnsSchoolFeesDelayResp.setApplyUserInfo(applyUserInfo);
                        return smsWnsSchoolFeesDelayResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (applyType == SCHOOL_FEES_DELAY_TYPE_ALLOWED) {
            Page<SmsWnsSchoolFeesDelayMpjResp> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsWnsSchoolFeesDelayDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsWnsSchoolFeesDelayDetail.class)
                    .selectAll(SmsWnsSchoolFeesDelay.class)
                    .selectAs(SmsWnsSchoolFeesDelay::getCreateTime, "createTime")
                    .selectAs(SmsWnsSchoolFeesDelayDetail::getId, "detailId")
                    .leftJoin(SmsWnsSchoolFeesDelay.class, SmsWnsSchoolFeesDelay::getId, SmsWnsSchoolFeesDelayDetail::getApplyId)
                    .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowUserId, userId)
                    .orderByDesc(SmsWnsSchoolFeesDelayDetail::getDetailAllowTime);

            mpjLambdaWrapper.and(wrapper -> {
                wrapper.eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_PASS)
                        .or()
                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_DENY);
            });
            if(!isNullOrEmpty(searchStr)){
                mpjLambdaWrapper.and(q ->{
                    q.like(SmsWnsSchoolFeesDelay::getStuName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getStuSex, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                            .or()
                            .like(SmsWnsSchoolFeesDelay::getMajorName, searchStr);
                });
            }
            smsWnsSchoolFeesDelayMpjMapper.selectJoinPage(page, SmsWnsSchoolFeesDelayMpjResp.class, mpjLambdaWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsExamineMPJResp -> {
                        SmsWnsSchoolFeesDelayResp schoolFeesDelayResp = new SmsWnsSchoolFeesDelayResp();
                        BeanUtils.copyProperties(smsExamineMPJResp, schoolFeesDelayResp);
                        schoolFeesDelayResp.setCreateTime(smsExamineMPJResp.getCreateTime());
                        schoolFeesDelayResp.setAllowStatus(smsExamineMPJResp.getDetailAllowStatus());

                        SmsUser applyUser = cacheUtil.getUserInfo(schoolFeesDelayResp.getUserId());
                        UserInfoResp applyUserInfo = new UserInfoResp();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, applyUserInfo);
                        }
                        schoolFeesDelayResp.setApplyUserInfo(applyUserInfo);

                        SmsUser allowUser = cacheUtil.getUserInfo(schoolFeesDelayResp.getDetailAllowUserId());
                        UserInfoResp allowUserInfo = new UserInfoResp();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, allowUserInfo);
                        }
                        schoolFeesDelayResp.setAllowUserInfo(allowUserInfo);

                        return schoolFeesDelayResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (applyType == SCHOOL_FEES_DELAY_TYPE_ALLOW_WAIT_ME) {
            List<String> roleList = cacheUtil.getRoleList(userId);

            //获取所有待审批申请流程节点
            List<SmsWnsSchoolFeesDelayDetail> allDetailList =
                    smsWnsSchoolFeesDelayDetailMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                            .lambda()
                            .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));

            List<SmsWnsSchoolFeesDelayDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessIsApplicationEdit()) {
                            if (!detail.getProcessObjectId().equals(userId)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessObjectId().equals(userId)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }


                        if (detail.getDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsWnsSchoolFeesDelayDetail preDetail =
                                smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                                        .lambda()
                                        .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, detail.getApplyId())
                                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, detail.getDetailSort() - 1)
                                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsWnsSchoolFeesDelayDetail::getId).collect(Collectors.toList());

                Page<SmsWnsSchoolFeesDelayMpjResp> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsWnsSchoolFeesDelayDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsWnsSchoolFeesDelayDetail.class)
                        .selectAll(SmsWnsSchoolFeesDelay.class)
                        .selectAs(SmsWnsSchoolFeesDelay::getCreateTime, "createTime")
                        .selectAs(SmsWnsSchoolFeesDelayDetail::getId, "detailId")
                        .leftJoin(SmsWnsSchoolFeesDelay.class, SmsWnsSchoolFeesDelay::getId, SmsWnsSchoolFeesDelayDetail::getApplyId)
                        .in(SmsWnsSchoolFeesDelayDetail::getId, detailIDList)
                        .orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime)
                        .orderByDesc(SmsWnsSchoolFeesDelayDetail::getDetailAllowTime)
                ;
                if(!isNullOrEmpty(searchStr)){
                    mpjLambdaWrapper.and(q ->{
                        q.like(SmsWnsSchoolFeesDelay::getStuName, searchStr)
                                .or()
                                .like(SmsWnsSchoolFeesDelay::getStuSex, searchStr)
                                .or()
                                .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                                .or()
                                .like(SmsWnsSchoolFeesDelay::getCollegeName, searchStr)
                                .or()
                                .like(SmsWnsSchoolFeesDelay::getMajorName, searchStr);
                    });
                }
                smsWnsSchoolFeesDelayMpjMapper.selectJoinPage(page, SmsWnsSchoolFeesDelayMpjResp.class, mpjLambdaWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsExamineMPJResp -> {
                            SmsWnsSchoolFeesDelayResp smsExamineResp = new SmsWnsSchoolFeesDelayResp();
                            BeanUtils.copyProperties(smsExamineMPJResp, smsExamineResp);
                            smsExamineResp.setApplyId(smsExamineMPJResp.getApplyId());
                            smsExamineResp.setCreateTime(smsExamineMPJResp.getCreateTime());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsExamineResp.getUserId());
                            UserInfoResp applyUserInfo = new UserInfoResp();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, applyUserInfo);
                            }
                            smsExamineResp.setApplyUserInfo(applyUserInfo);

                            return smsExamineResp;
                        })
                        .collect(Collectors.toList());
                total = (int) page.getTotal();

            }
        }
        return CommonResult.success(respList, total);
    }


    @Override
    public ResponseResult getSchoolFeesDelayDetail(String applyId, String userId) {
        if (isNullOrEmpty(applyId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(applyId);
        if (schoolFeesDelay == null || isNullOrEmpty(schoolFeesDelay.getId())) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }

        SmsWnsSchoolFeesDelayResp schoolFeesDelayResp = new SmsWnsSchoolFeesDelayResp();
        BeanUtils.copyProperties(schoolFeesDelay, schoolFeesDelayResp);
        schoolFeesDelayResp.setApplyId(schoolFeesDelay.getId());
        schoolFeesDelayResp.setDeliveryDate(TimeUtil.DateFormatSting(schoolFeesDelay.getDeliveryDate()));

        SmsUser smsUser = cacheUtil.getUserInfo(schoolFeesDelayResp.getUserId());
        UserInfoResp applyUserInfo = new UserInfoResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, applyUserInfo);
        }
        schoolFeesDelayResp.setApplyUserInfo(applyUserInfo);

        List<SmsWnsSchoolFeesDelayDetailResp> detailRespList =
                smsWnsSchoolFeesDelayDetailMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, applyId)
                        .orderByAsc(SmsWnsSchoolFeesDelayDetail::getDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsWnsSchoolFeesDelayDetailResp detailResp = new SmsWnsSchoolFeesDelayDetailResp();
                            BeanUtils.copyProperties(detail, detailResp);
                            detailResp.setDetailAllowOption(detail.getDetailAllowOption());
                            if(detailResp.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON){
                                SmsUser smsUser1 = smsUserMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsUser1)) {
                                    detailResp.setRealName(smsUser1.getRealName());
                                    detailResp.setHeadPic(smsUser1.getUserPic());
                                }
                            } else if(detailResp.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_ROLE){
                                SmsRole smsRole = smsRoleMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsRole)) {
                                    detailResp.setRealName(smsRole.getRoleName());
                                }
                            }
                            if (!isNullOrEmpty(detailResp.getDetailAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getDetailAllowUserId());
                                UserInfoResp userInfoResp = new UserInfoResp();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, userInfoResp);
                                }
                                detailResp.setAllowUserInfo(userInfoResp);
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        schoolFeesDelayResp.setDetailList(detailRespList);
        return CommonResult.success(schoolFeesDelayResp);
    }

    @Override
    public ResponseResult getSchoolFeesDelayOriginSettingProcess(String userId) {
        List<SmsWnsSchoolFeesDelayOriginSettingProcessResp> respList =
                smsWnsSchoolFeesDelayProcessMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayProcess>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsWnsSchoolFeesDelayProcess::getProcessIsUse,true)
                        .orderByAsc(SmsWnsSchoolFeesDelayProcess::getProcessSort))
                        .stream()
                        .map(process -> {
                            SmsWnsSchoolFeesDelayOriginSettingProcessResp schoolFeesDelayOriginSettingProcessResp = new SmsWnsSchoolFeesDelayOriginSettingProcessResp();
                            BeanUtils.copyProperties(process, schoolFeesDelayOriginSettingProcessResp);
                            return schoolFeesDelayOriginSettingProcessResp;
                        })
                        .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult selectAllSchoolFeesDelay(String deliveryDate,String stuName, Integer allowStatus, String collegeId, String majorId, String stuIdCard, Integer pageSize, Integer pageNum) {
        Page<SmsWnsSchoolFeesDelay> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SmsWnsSchoolFeesDelay> schoolFeesDelayLambdaQueryWrapper = new LambdaQueryWrapper<SmsWnsSchoolFeesDelay>()
                .orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
        if (!isNullOrEmpty(stuName)) {
            schoolFeesDelayLambdaQueryWrapper.like(SmsWnsSchoolFeesDelay::getStuName, stuName);
        }
        if(!isNullOrEmpty(allowStatus)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getAllowStatus,allowStatus);
        }
        if(!isNullOrEmpty(collegeId)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getCollegeId,collegeId);
        }
        if(!isNullOrEmpty(majorId)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getMajorId, majorId);
        }
        if(!isNullOrEmpty(stuIdCard)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getStuIdCard, stuIdCard);
        }
        if(!isNullOrEmpty(deliveryDate)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getDeliveryDate, deliveryDate);
        }

       smsWnsSchoolFeesDelayMapper.selectPage(page, schoolFeesDelayLambdaQueryWrapper);

        List<SmsWnsSchoolFeesDelayResp> schoolFeesDelayList = page.getRecords()
                .stream()
                .map(schoolFeesDelay -> {
                    SmsWnsSchoolFeesDelayResp smsWnsSchoolFeesDelayResp = new SmsWnsSchoolFeesDelayResp();
                    BeanUtils.copyProperties(schoolFeesDelay, smsWnsSchoolFeesDelayResp);
                    smsWnsSchoolFeesDelayResp.setApplyId(schoolFeesDelay.getId());
                    SmsUser smsUser = cacheUtil.getUserInfo(schoolFeesDelay.getUserId());
                    if (smsUser != null) {
                        UserInfoResp userInfoResp = new UserInfoResp();
                        BeanUtils.copyProperties(smsUser, userInfoResp);
                        smsWnsSchoolFeesDelayResp.setApplyUserInfo(userInfoResp);
                    }

                    return smsWnsSchoolFeesDelayResp;
        }).collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(schoolFeesDelayList, total);
    }

    @Override
    public ResponseResult selectStuAllSchoolFeesDelay(String deliveryDate, Integer allowStatus, String userId, Integer pageSize, Integer pageNum) {
        Page<SmsWnsSchoolFeesDelay> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SmsWnsSchoolFeesDelay> schoolFeesDelayLambdaQueryWrapper = new LambdaQueryWrapper<SmsWnsSchoolFeesDelay>()
                .eq(SmsWnsSchoolFeesDelay::getUserId,userId)
                .orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
        if (!isNullOrEmpty(deliveryDate)) {
            schoolFeesDelayLambdaQueryWrapper.like(SmsWnsSchoolFeesDelay::getDeliveryDate, deliveryDate);
        }
        if(!isNullOrEmpty(allowStatus)){
            schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getAllowStatus,allowStatus);
        }
        smsWnsSchoolFeesDelayMapper.selectPage(page, schoolFeesDelayLambdaQueryWrapper);

        List<SmsWnsSchoolFeesDelayResp> schoolFeesDelayList = page.getRecords()
                .stream()
                .map(schoolFeesDelay -> {
                    SmsWnsSchoolFeesDelayResp smsWnsSchoolFeesDelayResp = new SmsWnsSchoolFeesDelayResp();
                    BeanUtils.copyProperties(schoolFeesDelay, smsWnsSchoolFeesDelayResp);
                    smsWnsSchoolFeesDelayResp.setApplyId(schoolFeesDelay.getId());
                    SmsUser smsUser = cacheUtil.getUserInfo(schoolFeesDelay.getUserId());
                    if (smsUser != null) {
                        UserInfoResp userInfoResp = new UserInfoResp();
                        BeanUtils.copyProperties(smsUser, userInfoResp);
                        smsWnsSchoolFeesDelayResp.setApplyUserInfo(userInfoResp);
                    }

                    return smsWnsSchoolFeesDelayResp;
                }).collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(schoolFeesDelayList, total);
    }

    @Override
    @Async
    public Future<ResponseResult> tableDownload(String applyId, HttpServletResponse response) {
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(applyId);
        if (schoolFeesDelay == null || schoolFeesDelay.getId() == null) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST));
        }
        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getFILE_DOWNLOAD_PATH()
                : fileSavePathConstant.getFILE_DOWNLOAD_PATH_LINUX();

        String newFilePath = filePath + applyId + ".docx";
        String pdfFilePath = filePath + applyId + ".pdf";

        File pdfFile = new File(pdfFilePath);

        try {


            //图片
            List<String> picTagList = new ArrayList<>();
            //字段
            Map<String, Object> map = new HashMap<>();

            map.put("signTime", TimeUtil.DateHanZiSimpleFormat(schoolFeesDelay.getCreateTime()));
            map.put("stuName", schoolFeesDelay.getStuName());
            map.put("stuSex", schoolFeesDelay.getStuSex());
            map.put("collegeName", schoolFeesDelay.getCollegeName());
            map.put("majorName", schoolFeesDelay.getMajorName());
            map.put("stuIdCard", schoolFeesDelay.getStuIdCard());
            map.put("stuAddress", schoolFeesDelay.getStuAddress());
            map.put("delayReason", schoolFeesDelay.getDelayReason());
            map.put("shouldMoney", String.valueOf(schoolFeesDelay.getShouldMoney()));
            map.put("beforeMoney", String.valueOf(schoolFeesDelay.getBeforeMoney()));
            map.put("afterMoney", String.valueOf(schoolFeesDelay.getAfterMoney()));
            map.put("deliveryDate", TimeUtil.DateHanZiSimpleFormat(schoolFeesDelay.getDeliveryDate()));
            map.put("parentName", schoolFeesDelay.getParentName());
            map.put("parentTel", schoolFeesDelay.getParentTel());

            //申请人签字
            String[] splitStrName = schoolFeesDelay.getApplyName().split("=");
            String applyFileName = splitStrName[splitStrName.length - 1];
            File applyFile = new File(filePath + applyFileName);
            InputStream applyInputStream = new FileInputStream(applyFile);
            PictureRenderData picture = Pictures.ofStream(applyInputStream,
                    PictureType.PNG).size(60, 30).create();
            map.put("applyName", picture);
            picTagList.add("applyName");

            //获取初始流程
            List<SmsWnsSchoolFeesDelayProcess> processList = smsWnsSchoolFeesDelayProcessMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayProcess>()
                    .lambda()
                    .orderByAsc(SmsWnsSchoolFeesDelayProcess::getProcessSort));
            if (processList == null || processList.size() < 1) {
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
            }

            //获取申请流程
            List<SmsWnsSchoolFeesDelayDetail> detailList = smsWnsSchoolFeesDelayDetailMapper.selectList(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                    .lambda()
                    .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, applyId));
            for (SmsWnsSchoolFeesDelayProcess process : processList) {
                List<SmsWnsSchoolFeesDelayDetail> filterDetail = detailList
                        .stream()
                        .filter(detail -> detail.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterDetail.size() > 0) {
                    SmsWnsSchoolFeesDelayDetail detail = filterDetail.get(0);
                    if (detail.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_PASS || detail.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_FORCED_FINISH) {
                        map.put("allowStatus" + process.getProcessSort() + "", "同意");
                    } else if (detail.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_DENY || detail.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_FORCED_REJECT) {
                        map.put("allowStatus" + process.getProcessSort() + "", "拒绝");
                    } else {
                        map.put("allowStatus" + process.getProcessSort() + "", "");
                    }

                    map.put("allowOption" + process.getProcessSort() + "", detail.getDetailAllowOption());

                    //添加签名
                    if (isNullOrEmpty(detail.getDetailAllowSign())) {
                        map.put("allowSign" + process.getProcessSort() + "", "");
                    } else {
                        String[] splitStr = detail.getDetailAllowSign().split("=");
                        String fileName = splitStr[splitStr.length - 1];

                        File file = new File(filePath + fileName);
                        if (file.exists()) {
                            InputStream inputStream = new FileInputStream(file);
                            PictureRenderData pictures = Pictures.ofStream(inputStream,
                                    PictureType.PNG).size(60, 60).create();

                            map.put("allowSign" + process.getProcessSort() + "", pictures);
                            picTagList.add("allowSign" + process.getProcessSort());
                        }
                    }

                    //添加印章
                    if (isNullOrEmpty(detail.getDetailAllowStamp())) {
                        map.put("allowStamp" + process.getProcessSort() + "", "");
                    } else {
                        String[] splitStr = detail.getDetailAllowStamp().split("=");
                        String fileName = splitStr[splitStr.length - 1];

                        File file = new File(filePath + fileName);
                        if (file.exists()) {
                            InputStream inputStream = new FileInputStream(file);
                            PictureRenderData pictures = Pictures.ofStream(inputStream,
                                    PictureType.PNG).size(60, 60).create();

                            map.put("allowStamp" + process.getProcessSort() + "", pictures);
                            picTagList.add("allowStamp" + process.getProcessSort());
                        }

                    }

                    //审批时间
                    if (isNullOrEmpty(detail.getDetailAllowTime())) {
                        map.put("detailAllowTime" + process.getProcessSort() + "", "");
                    } else {
                        map.put("detailAllowTime" + process.getProcessSort() + "", TimeUtil.DateHanZiSimpleFormat(detail.getDetailAllowTime()));
                    }
                } else {
                    map.put("allowStatus" + process.getProcessSort() + "", "");
                    map.put("allowOption" + process.getProcessSort() + "", "");
                    map.put("allowSign" + process.getProcessSort() + "", "");
                    map.put("allowStamp" + process.getProcessSort() + "", "");
                    map.put("detailAllowTime" + process.getProcessSort() + "", "");
                }
            }


            ClassPathResource resource = new ClassPathResource("applyTemplates/schoolFeesDelay.docx");
            InputStream is = resource.getInputStream();
            FileOutputStream outputStream = new FileOutputStream(newFilePath);

            XWPFTemplate template = XWPFTemplate.compile(is);

            //配置图片标签
            Configure config = template.getConfig();
            for (String tag : picTagList
            ) {
                config.customPolicy(tag, new PictureRenderPolicy());
            }
            template.render(map);

            template.write(outputStream);

            is.close();
            outputStream.close();
            template.close();

            //word转pdf
            File destOri = new File(newFilePath);
            FileInputStream fileInputStream = new FileInputStream(destOri);
            FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath);

            Document document = new Document();
            document.loadFromStream(fileInputStream, FileFormat.Docx);
            //保存为PDF
            document.saveToFile(pdfFilePath, FileFormat.PDF);


            fileInputStream.close();
            fileOutputStream.close();
            document.close();

            log.debug("文件生成完成!");
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        try {
            // 加载PDF文档
            PDDocument doc = PDDocument.load(pdfFile);
            doc.setAllSecurityToBeRemoved(true);
            // 创建水印
            String watermark = "南充电影工业职业学院";
            PDPageContentStream contentStream;

            for (PDPage page : doc.getPages()) {
                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);

                //加载字体
                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
                InputStream is = resource.getInputStream();
                PDFont font = PDType0Font.load(doc, is);


                int startX = 0; // 起始位置 x 坐标
                int startY = 0; // 起始位置 y 坐标
                float angle = -45; // 角度
                float interval = 250; // 间隔
                float opacity = 0.3f; // 透明度
                int colorR = 127; // 颜色 red 值
                int colorG = 127; // 颜色 green 值
                int colorB = 127; // 颜色 blue 值

                //透明的
                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
                r0.setNonStrokingAlphaConstant(opacity);
                r0.setAlphaSourceFlag(true);
                contentStream.setGraphicsStateParameters(r0);

                //水印颜色
                contentStream.setNonStrokingColor(colorR, colorG, colorB);
                contentStream.beginText();
                contentStream.setFont(font, 30f);

                int x_times = (int) Math.ceil(page.getMediaBox().getWidth() / interval);
                int y_times = (int) Math.ceil(page.getMediaBox().getHeight() / interval);
                for (int x = startX; x <= x_times; x++) {
                    for (int y = startY; y <= y_times; y++) {
                        contentStream.setTextRotation(angle, (x * interval), (y * interval));
                        contentStream.showText(watermark);
                    }
                }
                contentStream.endText();
                contentStream.restoreGraphicsState();
                contentStream.close();
                is.close();
            }

//            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.pdf;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("家庭经济困难学生学费缓缴申请书预览.pdf", "utf-8"));
            response.setHeader("file-name", URLEncoder.encode("家庭经济困难学生学费缓缴申请书预览.pdf", "utf-8"));
            response.setHeader("file-type","download");
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
            //刷新缓冲
            response.flushBuffer();

            // 保存PDF文档
            doc.save(response.getOutputStream());
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));

        }
        return null;
    }

    @Override
    @Async
    public Future<ResponseResult> exportSchoolFeesDelay(SmsWnsSchoolFeesDelayExportReq schoolFeesDelayExportReq, HttpServletResponse response) {
        if (isNullOrEmpty(schoolFeesDelayExportReq.getIsExportProcess())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        try {
            LambdaQueryWrapper<SmsWnsSchoolFeesDelay> schoolFeesDelayLambdaQueryWrapper = new LambdaQueryWrapper<SmsWnsSchoolFeesDelay>()
                    .orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
            if (!isNullOrEmpty(schoolFeesDelayExportReq.getStuName())) {
                schoolFeesDelayLambdaQueryWrapper.like(SmsWnsSchoolFeesDelay::getStuName, schoolFeesDelayExportReq.getStuName());
            }
            if(!isNullOrEmpty(schoolFeesDelayExportReq.getAllowStatus())){
                schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getAllowStatus,schoolFeesDelayExportReq.getAllowStatus());
            }
            if(!isNullOrEmpty(schoolFeesDelayExportReq.getCollegeId())){
                schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getCollegeId,schoolFeesDelayExportReq.getCollegeId());
            }
            if(!isNullOrEmpty(schoolFeesDelayExportReq.getMajorId())){
                schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getMajorId, schoolFeesDelayExportReq.getMajorId());
            }
            if(!isNullOrEmpty(schoolFeesDelayExportReq.getStuIdCard())){
                schoolFeesDelayLambdaQueryWrapper.eq(SmsWnsSchoolFeesDelay::getStuIdCard, schoolFeesDelayExportReq.getStuIdCard());
            }
            schoolFeesDelayLambdaQueryWrapper.orderByDesc(SmsWnsSchoolFeesDelay::getCreateTime);
            List<SmsWnsSchoolFeesDelay> list = smsWnsSchoolFeesDelayMapper.selectList(schoolFeesDelayLambdaQueryWrapper);
            //表头数据
            String[] header = schoolFeesDelayExportReq.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            //声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list != null && list.size() > 0) {
                sheetNum = Math.ceil((double) list.size() / PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    //生成一个表格，设置表格名称为"资源导出表"
                    HSSFSheet sheet = workbook.createSheet("家庭经济困难学生学费缓缴申请书记录导出表" + (k + 1));

                    //设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    //创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10);//字号
                    f.setBold(true);//加粗
                    headerStyle.setFont(f);
                    //创建第一行表头
                    HSSFRow headrow = sheet.createRow(0);

                    //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        //创建一个单元格
                        HSSFCell cell = headrow.createCell(i);

                        if (i == 0) {
                            //创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            //将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }
                        //创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsWorkGroupApplication.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }

                    //判断是否需要添加流程表头
                    if (schoolFeesDelayExportReq.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                        List<SmsWnsSchoolFeesDelayProcess> processList =
                                smsWnsSchoolFeesDelayProcessMapper.selectList(new QueryWrapper<>());
                        if (processList != null && processList.size() > 0) {
                            int origin_num = header.length + 1;
                            for (SmsWnsSchoolFeesDelayProcess process : processList) {
                                String process_name = process.getProcessName();
                                addProcessTableHead(headrow, headerStyle, origin_num, process_name);
                                origin_num += 4;
                            }
                        }
                    }

                    int range = PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = list.size() - (PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        //创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsWnsSchoolFeesDelay schoolFeesDelay = list.get((PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(schoolFeesDelay), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if (map.get(header[j]) instanceof Long) {
                                rowContent = TimeUtil.DateformatTimestamp((long) map.get(header[j]));
                            } else {
                                rowContent = String.valueOf( map.get(header[j]));
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                        if (schoolFeesDelayExportReq.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                            List<SmsWnsSchoolFeesDelayProcess> processList =
                                    smsWnsSchoolFeesDelayProcessMapper.selectList(new QueryWrapper<>());
                            if (processList != null && processList.size() > 0) {
                                Integer origin_num = header.length + 1;
                                for (SmsWnsSchoolFeesDelayProcess process : processList) {
                                    SmsWnsSchoolFeesDelayDetail detail =
                                            smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                                                    .lambda()
                                                    .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, schoolFeesDelay.getId())
                                                    .eq(SmsWnsSchoolFeesDelayDetail::getProcessId, process.getId()));
                                    if (detail == null || detail.getId() == null) {
                                        origin_num += 4;
                                    } else {
                                        //审批人
                                        SmsUser user = cacheUtil.getUserInfo(detail.getDetailAllowUserId());
                                        if (user == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(user.getRealName()));
                                        }

                                        //审批时间
                                        Date allow_time = detail.getDetailAllowTime();
                                        if (allow_time == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(TimeUtil.DateHanZiSimpleFormat(allow_time)));
                                        }

                                        //审批状态
                                        Integer allow_status = detail.getDetailAllowStatus();
                                        if (allow_status == EXAMINE_STATUS_PASS || allow_status == EXAMINE_STATUS_FORCED_FINISH) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("同意"));
                                        } else if (allow_status == EXAMINE_STATUS_DENY || allow_status == EXAMINE_STATUS_FORCED_REJECT) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("拒绝"));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        }

                                        //审批意见
                                        String allow_option = detail.getDetailAllowOption();
                                        if (isNullOrEmpty(allow_option)) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(allow_option));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

//            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("家庭经济困难学生学费缓缴申请书记录导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("家庭经济困难学生学费缓缴申请书记录导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//            //刷新缓冲
            response.flushBuffer();
            //workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }



    private void addProcessTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer origin_cell_num, String originHeadContent) {
        Integer cell_num = origin_cell_num;

        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批人");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批时间");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批状态");
        setTableHead(headRow, headerStyle, cell_num, originHeadContent + "审批意见");

    }
    private void setTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer cell_num, String headContent) {
        HSSFCell cell = headRow.createCell(cell_num);
        //创建一个内容对象
        HSSFRichTextString text = new HSSFRichTextString(headContent);

        //将内容对象的文字内容写入到单元格中
        cell.setCellValue(text);
        cell.setCellStyle(headerStyle);
    }

    @Override
    @Transactional
    public ResponseResult forcedFinishSchoolFeesDelay(String applyId, String userId) {
        //校验数据
        if (isNullOrEmpty(applyId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(applyId);
        if(isNullOrEmpty(schoolFeesDelay)){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }
        if(schoolFeesDelay.getAllowStatus() != SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_FORCED);
        }
        //修改审批表状态为通过
        schoolFeesDelay.setAllowStatus(SCHOOL_FEES_DELAY_STATUS_PASS);
        schoolFeesDelay.setEndTime(new Date());
        smsWnsSchoolFeesDelayMapper.updateById(schoolFeesDelay);

        //修改节点为强制归档
        SmsWnsSchoolFeesDelayDetail schoolFeesDelayDetail = new SmsWnsSchoolFeesDelayDetail();
        schoolFeesDelayDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_FORCED_FINISH);
        schoolFeesDelayDetail.setDetailAllowUserId(userId);
        schoolFeesDelayDetail.setDetailAllowTime(new Date());
        smsWnsSchoolFeesDelayDetailMapper.update(schoolFeesDelayDetail,new LambdaQueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                .eq(SmsWnsSchoolFeesDelayDetail::getApplyId,applyId)
                .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus,SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(applyId);
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedTorsionSchoolFeesDelay(SmsWnsSchoolFeesDelayDetailTorsionReq torsionReq) {
        if(isNullOrEmpty(torsionReq.getDetailId(),torsionReq.getApplyId(),torsionReq.getProcessObjectType(),torsionReq.getProcessObjectId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验申请表 节点表
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(torsionReq.getApplyId());
        if(isNullOrEmpty(schoolFeesDelay)){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }
        SmsWnsSchoolFeesDelayDetail schoolFeesDelayDetail = smsWnsSchoolFeesDelayDetailMapper.selectById(torsionReq.getDetailId());
        if(isNullOrEmpty(schoolFeesDelayDetail)){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_DETAIL_NOT_FORCED);
        }
        //只有待审批才能强制流转
        if(schoolFeesDelayDetail.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_TORSION);
        }
        schoolFeesDelayDetail.setProcessObjectType(torsionReq.getProcessObjectType());
        schoolFeesDelayDetail.setProcessObjectId(torsionReq.getProcessObjectId());
        smsWnsSchoolFeesDelayDetailMapper.updateById(schoolFeesDelayDetail);
        //消息通知
        //判断第一节点直接发消息,其他要前节点审批后才发该节点通知
        boolean flag = true;
        if(!schoolFeesDelayDetail.getDetailSort().equals(1)){
            SmsWnsSchoolFeesDelayDetail beforeDetail = smsWnsSchoolFeesDelayDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                    .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, torsionReq.getApplyId())
                    .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, schoolFeesDelayDetail.getDetailSort() - 1));
            if(beforeDetail.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_PASS){
                flag = false;
            }
        }
        if(flag) {
            RangeTypeEnum rangeTypeEnum;
            if (schoolFeesDelayDetail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeList = new ArrayList<>();
            rangeList.add(schoolFeesDelayDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(torsionReq.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeList,
                    schoolFeesDelayDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult replaceApplySchoolFeesDelay(String userId, SmsWnsSchoolFeesDelayAllowReq allowReq) {
        if (isNullOrEmpty(allowReq.getApplyId()) || isNullOrEmpty(allowReq.getDetailId())
                || isNullOrEmpty(allowReq.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowReq.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_PASS && allowReq.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsSchoolFeesDelayDetail schoolFeesDelayDetail =
                smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                        .lambda()
                        .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                        .eq(SmsWnsSchoolFeesDelayDetail::getId, allowReq.getDetailId())
                        .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));
        if (schoolFeesDelayDetail == null || isNullOrEmpty(schoolFeesDelayDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
        }


        if (!schoolFeesDelayDetail.getDetailSort().equals(1)) {
            SmsWnsSchoolFeesDelayDetail preDetail =
                    smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                            .lambda()
                            .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, schoolFeesDelayDetail.getDetailSort() - 1));
            if (preDetail != null && !isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != SCHOOL_FEES_DELAY_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_ALLOW_FAIL);
                }
            }
        }


        SmsWnsSchoolFeesDelayDetail allowDetail = new SmsWnsSchoolFeesDelayDetail();
        allowDetail.setId(allowReq.getDetailId());
        allowDetail.setDetailAllowStatus(allowReq.getDetailAllowStatus());
        if (!isNullOrEmpty(allowReq.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowReq.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(userId);
        allowDetail.setDetailAllowSign(allowReq.getDetailAllowSign());
        allowDetail.setDetailAllowStamp(allowReq.getDetailAllowStamp());
        smsWnsSchoolFeesDelayDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsWnsSchoolFeesDelayDetailMapper.selectCount(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                .lambda()
                .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId()));
        if (detailCount.equals(schoolFeesDelayDetail.getDetailSort()) || allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_DENY) {
            is_done = true;

            SmsWnsSchoolFeesDelay updateApplication = new SmsWnsSchoolFeesDelay();
            updateApplication.setId(allowReq.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowReq.getDetailAllowStatus());
            smsWnsSchoolFeesDelayMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        if (allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_DENY) {
            SmsWnsSchoolFeesDelayDetail updateDenyDetail = new SmsWnsSchoolFeesDelayDetail();
            updateDenyDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_DENY_FINISH);
            smsWnsSchoolFeesDelayDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                    .lambda()
                    .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                    .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowReq.getDetailAllowStatus() == SCHOOL_FEES_DELAY_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowReq.getApplyId(), userId, result_status);
        } else {
            SmsWnsSchoolFeesDelayDetail nextDetail =
                    smsWnsSchoolFeesDelayDetailMapper.selectOne(new QueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                            .lambda()
                            .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsWnsSchoolFeesDelayDetail::getDetailSort, schoolFeesDelayDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == SCHOOL_FEES_DELAY_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowReq.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedRejectSchoolFeesDelay(SmsWnsSchoolFeesDelayForcedReq forcedReq, String userId) {
        if(isNullOrEmpty(forcedReq.getApplyId(),forcedReq.getDetailAllowOption())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(forcedReq.getApplyId());
        if(isNullOrEmpty(schoolFeesDelay)){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }
        //总状态只有待审批才能强制驳回
        Integer allowStatus = schoolFeesDelay.getAllowStatus();
        if(allowStatus != SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_FORCED_REJECT);
        }
        //修改申请表状态为驳回
        schoolFeesDelay.setAllowStatus(SCHOOL_FEES_DELAY_STATUS_DENY);
        schoolFeesDelay.setEndTime(new Date());
        smsWnsSchoolFeesDelayMapper.updateById(schoolFeesDelay);
        //修改节点状态 和审批人 时间
        SmsWnsSchoolFeesDelayDetail schoolFeesDelayDetail = new SmsWnsSchoolFeesDelayDetail();
        schoolFeesDelayDetail.setDetailAllowUserId(userId);
        schoolFeesDelayDetail.setDetailAllowStatus(SCHOOL_FEES_DELAY_STATUS_FORCED_REJECT);
        schoolFeesDelayDetail.setDetailAllowTime(new Date());
        schoolFeesDelayDetail.setDetailAllowOption(forcedReq.getDetailAllowOption());
        smsWnsSchoolFeesDelayDetailMapper.update(schoolFeesDelayDetail, new LambdaQueryWrapper<SmsWnsSchoolFeesDelayDetail>()
                .eq(SmsWnsSchoolFeesDelayDetail::getApplyId, forcedReq.getApplyId())
                .eq(SmsWnsSchoolFeesDelayDetail::getDetailAllowStatus, SCHOOL_FEES_DELAY_STATUS_WAIT_ALLOW));
        //消息提醒
        newTipsUtil.cancelFinishTips(forcedReq.getApplyId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deletedSchoolFeesDelay(String applyId) {
        SmsWnsSchoolFeesDelay schoolFeesDelay = smsWnsSchoolFeesDelayMapper.selectById(applyId);
        if (isNullOrEmpty(schoolFeesDelay)) {
            return CommonResult.failed(CommonCodeEnum.SCHOOL_FEES_DELAY_NOT_EXIST);
        }

        //删除消息
        List<SmsNewTips> smsNewTipList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>().eq(SmsNewTips::getEventId, applyId));
        if (!smsNewTipList.isEmpty()) {
            List<String> newTipsIdList = smsNewTipList.stream().map(SmsNewTips::getId).collect(Collectors.toList());
            smsNewTipsMapper.deleteBatchIds(newTipsIdList);
            smsNewTipsRecordMapper.delete(new LambdaQueryWrapper<SmsNewTipsRecord>().in(SmsNewTipsRecord::getRecordTipsId, newTipsIdList));
        }
        //删除申请表
        smsWnsSchoolFeesDelayMapper.deleteById(applyId);

        //删除节点
        smsWnsSchoolFeesDelayDetailMapper.delete(new LambdaQueryWrapper<SmsWnsSchoolFeesDelayDetail>().eq(SmsWnsSchoolFeesDelayDetail::getApplyId, applyId));

        return CommonResult.success();
    }
}
